

/**
 * \file   BIterator.h
 * \author Babinot Alexandre
 *  \version 1.0
 *  \date 24 janvier 2012
 */

using namespace std;
#include<iterator>
#include"barbre.h"
template<class T,class Compare>
class BArbre;
/**
 *\class BNodeIter
 *
 * \brief classe permettant d'utiliser un itérateur
 */
template<class T>
class BNodeIter : public iterator <input_iterator_tag, Node<T> > {
    protected:
        Node<T>* m_node;
		size_t vector_i;
		size_t point_i;
		int already_pass;
        Node<T>* root;

		std::vector< Node<T>* > vector_stack; //pile de noeud permettant la gestion récursive 
						
		std::vector<int> last_id;//pile de noeud permettant de récupérer le pointeur correpondant au noeud en cours d'utilisation dans la pile
						
    public:
    /**
     * \fn BNodeIter(BArbre<T,std::greater<int> > * B)
     *  \brief Constructeur d'un nouvel itérateur
     *  \param B Barbre sur lequel l'itérateur va itérer.
     */
		BNodeIter(BArbre<T,std::greater<int> > * B);
    /**
     * \fn operator++(int)
     *  \brief Surcharge de l'opérateur ++ pour l'incrémentation de l'itérateur
     */
		BNodeIter& operator++(int);
    /**
     * \fn operator=(int)
     *  \brief Surcharge de l'opérateur = pour l'affectation d'un itérateur
     */
        BNodeIter& operator=(Node<T>* node_copy);
    /**
     * \fn operator*
     *  \brief Surcharge de l'opérateur * pour récupérer la valeur de l'itérateur
     */        
        T operator*(void);

};

template<class T>
        BNodeIter<T>::BNodeIter(BArbre<T,std::greater<int> > * B) {
			m_node=B->getRoot();
			root=B->getRoot();
						already_pass=0;
						point_i=0;
						vector_i=0;
		}
template<class T>
        BNodeIter<T>& BNodeIter<T>::operator++(int) { //++m_node ; return *this ;
			int stop=0;			
			while (stop==0){
				stop=1;
				if (vector_i!=m_node->getPNodesVector().size()-2 && already_pass==0){ //recherche sur les clés
					++vector_i;
					return *this;
				}else{ //toutes les clé du noeud passées, remontée dans l'arbre ou descente
					
					vector_stack.push_back(m_node);

					if (m_node->getPNodesVector().at(point_i)->getPointeur()){ //si on n'est pas au dernier pointeur du noeud (pointeur != 0)
						m_node=m_node->getPNodesVector().at(point_i)->getPointeur();
						++point_i; // position du prochain pointeur à tester dans le noeud anciennement courant
						last_id.push_back(point_i); //enregistrement de l'index du pointeur du node courant
						already_pass=0;
						point_i=0;
						vector_i=0;
						return *this;
					}
					else{
						//supprime le noeud dont la parcours est fini, le noeud en dernière position est son parent.
						vector_stack.erase(vector_stack.end()-1);

						if (last_id.size()==0){
							return *this;							
						}

						//on récupère l'index du parcours de pointeurs dans la pile de pointeur
						point_i=last_id.back(); //récupération du pointeur
	

						last_id.erase(last_id.end()-1);


						//on récupère le noeud parent à la fin de la pile de noeud
						m_node=vector_stack.back();	

						//supprime le noeud parent de la liste
						vector_stack.erase(vector_stack.end()-1);


						already_pass=1;
						stop=0;
					}
				}

			}
			//évite un warning de compilation mais c'est un code mort
			return *this;
 		}
template<class T>
        BNodeIter<T>& BNodeIter<T>::operator=(Node<T>* node_copy) {
			m_node = node_copy ;
			return *this ;
		}
template<class T>
        T BNodeIter<T>::operator*(void) {
			if (last_id.size()==0 && m_node!=root)
				return 0;						
			return m_node->getPNodesVector().at(vector_i)->getValeur();
		}

